package com.kingboy.kbg.auth.common.jwt;

import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

/**
 * Create By 郭金宝 on 2018/6/15.<br>
 */
@Slf4j
public class RsaKeyHelper {
    /**
     * 获取公钥,用于解析token
     *
     * @param filename
     * @return
     * @throws Exception
     */
    public PublicKey getPublicKey(String filename) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
        log.info("PublicKey is : "+filename);
//        InputStream resourceAsStream = new FileInputStream(filename);
        InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(filename);
        DataInputStream dis = new DataInputStream(resourceAsStream);
        byte[] keyBytes = new byte[resourceAsStream.available()];
        dis.readFully(keyBytes);
        dis.close();
        //？？？？
        log.info(new String(keyBytes));
        String str = new String(keyBytes);
        byte[] keyBytesBase = Base64.decode(str);
        X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytesBase);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        return kf.generatePublic(spec);
    }

    /**
     * 获取密钥 用于生成token
     *
     * @param filename
     * @return
     * @throws Exception
     */
    public PrivateKey getPrivateKey(String filename) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
        log.info("PrivateKey is : "+filename);
//        InputStream resourceAsStream = new FileInputStream(filename);
        InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(filename);
//        log.info("resourceAsStream : "+new String(ByteStreams.toByteArray(resourceAsStream)));
        DataInputStream dis = new DataInputStream(resourceAsStream);
        byte[] keyBytes = new byte[resourceAsStream.available()];
        dis.readFully(keyBytes);
        dis.close();
        log.info(new String(keyBytes));
        String str = new String(keyBytes);
        byte[] keyBytesBase = Base64.decode(str);
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytesBase);
        KeyFactory kf = KeyFactory.getInstance("RSA");
        log.info(kf.generatePrivate(spec).getAlgorithm());
        return kf.generatePrivate(spec);
    }

    /**
     * 生成rsa公钥和密钥
     *
     * @param publicKeyFilename
     * @param privateKeyFilename
     * @param password
     * @throws IOException
     * @throws NoSuchAlgorithmException
     */
    public void generateKey(String publicKeyFilename, String privateKeyFilename, String password) throws IOException, NoSuchAlgorithmException {
        log.info("generateKey publicKeyFilename : "+publicKeyFilename+" privateKeyFilename :" + privateKeyFilename + " password : "+password);
//      //实例化密钥对生成器
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        SecureRandom secureRandom = new SecureRandom(password.getBytes());
        // 初始化密钥对生成器
        keyPairGenerator.initialize(1024, secureRandom);
        // 生成密钥对
        KeyPair keyPair = keyPairGenerator.genKeyPair();
        //公钥
        RSAPublicKey publicKey=(RSAPublicKey)keyPair.getPublic();
        // 得到公钥字符串
        String publicKeyString = Base64.encode(publicKey.getEncoded());
//        byte[] publicKeyBytes = keyPair.getPublic().getEncoded();
        byte[] publicKeyBytes = publicKeyString.getBytes();
        log.info("PUBLIC_KEY："+publicKeyString);
        FileOutputStream fos = new FileOutputStream(publicKeyFilename);
        fos.write(publicKeyBytes);
        fos.close();
        //私钥
        //私钥
        RSAPrivateKey privateKey=(RSAPrivateKey) keyPair.getPrivate();
        // 得到私钥字符串
        String privateKeyString = Base64.encode(privateKey.getEncoded());
//        byte[] privateKeyBytes = keyPair.getPrivate().getEncoded();
        byte[] privateKeyBytes = privateKeyString.getBytes();
        log.info("PRIVATE_KEY："+privateKeyString);
        fos = new FileOutputStream(privateKeyFilename);
        fos.write(privateKeyBytes);
        fos.close();
    }

    /**
     * 生存rsa公钥和密钥
     *
     * @param password
     * @throws IOException
     * @throws NoSuchAlgorithmException
     */
    public static Map<String, byte[]> generateKey(String password) throws NoSuchAlgorithmException {
        log.info("generateKey password : "+password);
        //RSA算法密钥对
        //实例化KeyPairGenerator对象
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        SecureRandom secureRandom = new SecureRandom(password.getBytes());
        //初始化KeyPairGenerator对象
        keyPairGenerator.initialize(1024, secureRandom);
        //生成keyPair对象
        KeyPair keyPair = keyPairGenerator.genKeyPair();
        byte[] publicKeyBytes = keyPair.getPublic().getEncoded();
        byte[] privateKeyBytes = keyPair.getPrivate().getEncoded();
        Map<String, byte[]> map = new HashMap<>();
        map.put("pub", publicKeyBytes);
        map.put("pri", privateKeyBytes);
        return map;
    }

    public static void main(String[] args) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
//        final String pubkey = "D:/pub.key";
//        final String pribkey = "D:/pri.key";
        final String pubkey = "client/pub.key";
        final String pribkey = "app/pri.key";
        final String password = "123456";
        RsaKeyHelper rsaKeyHelper = new RsaKeyHelper();
//        rsaKeyHelper.generateKey(pubkey,pribkey,password);
        RSAPrivateKey rsaPrivateKey = (RSAPrivateKey)rsaKeyHelper.getPrivateKey(pribkey);
//        InputStream resourceAsStream = new FileInputStream(pribkey);
//        DataInputStream dis = new DataInputStream(resourceAsStream);
//        byte[] keyBytes = new byte[resourceAsStream.available()];
//        dis.readFully(keyBytes);
//        dis.close();
//        keyBytes = Base64.decode(new String(keyBytes));
//        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
//        KeyFactory kf = KeyFactory.getInstance("RSA");
//        RSAPrivateKey rsaPrivateKey = (RSAPrivateKey)kf.generatePrivate(spec);
        log.info(rsaPrivateKey.getPrivateExponent().toString());
        RSAPublicKey rsaPublicKey = (RSAPublicKey)rsaKeyHelper.getPublicKey(pubkey);
        log.info(rsaPublicKey.getPublicExponent().toString());
    }

}
